home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / network / ka9q / ka9q_src.arc / NRS.C < prev    next >
C/C++ Source or Header  |  1988-07-28  |  6KB  |  268 lines

  1.  
  2. /* This module implements the serial line framing method used by
  3.  * net/rom nodes.  This allows the net/rom software to talk to
  4.  * an actual net/rom over its serial interface, which is useful
  5.  * if we want to do packet switching for multi-line wormholes.
  6.  */
  7. #include <stdio.h>
  8. #include "global.h"
  9. #include "mbuf.h"
  10. #include "iface.h"
  11. #include "ax25.h"
  12. #include "nrs.h"
  13. #ifdef UNIX    /* BSD or SYS5 */
  14. #include "unix.h"
  15. #else
  16. #ifdef ATARI_ST
  17. #include "st.h"
  18. #else
  19. #include "pc.h"
  20. #include "asy.h"
  21. #endif        /* ATARI_ST */
  22. #endif        /* BSD or SYS5 */
  23. #include "trace.h"
  24.  
  25. int asy_output();
  26.  
  27. /* control structures, sort of overlayed on async control blocks */
  28. struct nrs nrs[ASY_MAX];
  29.  
  30. /* Send a raw net/rom serial frame */
  31. nrs_raw(interface,bp)
  32. struct interface *interface;
  33. struct mbuf *bp;
  34. {
  35.     dump(interface,IF_TRACE_OUT,TRACE_AX25,bp) ;
  36.     
  37.     /* Queue a frame on the output queue and start transmitter */
  38.     nrsq(interface->dev,bp);
  39. }
  40.  
  41. /* Encode a raw packet in net/rom framing, put on link output queue, and kick
  42.  * transmitter
  43.  */
  44. static
  45. nrsq(dev,bp)
  46. int16 dev;        /* Serial line number */
  47. struct mbuf *bp;    /* Buffer to be sent */
  48. {
  49.     register struct nrs *sp;
  50.     struct mbuf *nrs_encode();
  51.  
  52.     if((bp = nrs_encode(bp)) == NULLBUF)
  53.         return;    
  54.  
  55.     sp = &nrs[dev];
  56.     enqueue(&sp->sndq,bp);
  57.     sp->sndcnt++;
  58.     if(sp->tbp == NULLBUF)
  59.         nrasy_start(dev);
  60. }
  61.  
  62. /* Start output, if possible, on asynch device dev */
  63. static
  64. nrasy_start(dev)
  65. int16 dev;
  66. {
  67.     register struct nrs *sp;
  68.  
  69.     if(!stxrdy(dev))
  70.         return;        /* Transmitter not ready */
  71.  
  72.     sp = &nrs[dev];
  73.     if(sp->tbp != NULLBUF){
  74.         /* transmission just completed */
  75.         free_p(sp->tbp);
  76.         sp->tbp = NULLBUF;
  77.     }
  78.     if(sp->sndq == NULLBUF)
  79.         return;    /* No work */
  80.  
  81.     sp->tbp = dequeue(&sp->sndq);
  82.     sp->sndcnt--;
  83.     asy_output(dev,sp->tbp->data,sp->tbp->cnt);
  84. }
  85.  
  86. /* Encode a packet in net/rom serial format */
  87. static
  88. struct mbuf *
  89. nrs_encode(bp)
  90. struct mbuf *bp;
  91. {
  92.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  93.     register char *cp;
  94.     char c;
  95.     unsigned char csum = 0 ;
  96.  
  97.     /* Allocate output mbuf that's twice as long as the packet.
  98.      * This is a worst-case guess (consider a packet full of STX's!)
  99.      * Add five bytes for STX, ETX, checksum, and two nulls.
  100.      */
  101.     lbp = alloc_mbuf(2*len_mbuf(bp) + 5);
  102.     if(lbp == NULLBUF){
  103.         /* No space; drop */
  104.         free_p(bp);
  105.         return NULLBUF;
  106.     }
  107.     cp = lbp->data;
  108.  
  109.     *cp++ = STX ;
  110.  
  111.     /* Copy input to output, escaping special characters */
  112.     while(pullup(&bp,&c,1) == 1){
  113.         switch(c & 0xff){    /* DG2KK: was: uchar(c) */
  114.         case STX:
  115.         case ETX:
  116.         case DLE:
  117.             *cp++ = DLE;
  118.             /* notice drop through to default */
  119.         default:
  120.             *cp++ = c;
  121.         }
  122.         csum += (c & 0xff);    /* DG2KK: was: uchar(c) */
  123.     }
  124.     *cp++ = ETX;
  125.     *cp++ = csum ;
  126.     *cp++ = NUL ;
  127.     *cp++ = NUL ;
  128.     
  129.     lbp->cnt = cp - lbp->data;
  130.     return lbp;
  131. }
  132. /* Process incoming bytes in net/rom serial format
  133.  * When a buffer is complete, return it; otherwise NULLBUF
  134.  */
  135. static
  136. struct mbuf *
  137. nrs_decode(dev,c)
  138. int16 dev;    /* net/rom unit number */
  139. char c;        /* Incoming character */
  140. {
  141.     struct mbuf *bp;
  142.     register struct nrs *sp;
  143.  
  144.     sp = &nrs[dev];
  145.     switch(sp->state) {
  146.         case NRS_INTER:
  147.             if ((c & 0xff) == STX) {    /* DG2KK look for start of frame */
  148.                 sp->state = NRS_INPACK ;    /* we're in a packet */
  149.                 sp->csum = 0 ;                /* reset checksum */
  150.             }
  151.             return NULLBUF ;
  152.             break ;    /* just for yucks */
  153.         case NRS_CSUM:
  154.             bp = sp->rbp ;
  155.             sp->rbp = NULLBUF ;
  156.             sp->rcnt = 0 ;
  157.             sp->state = NRS_INTER ;    /* go back to inter-packet state */
  158.             if (sp->csum == (c & 0xff)) {
  159.                 sp->packets++ ;
  160.                 return bp ;
  161.             }
  162.             else {
  163.                 free_p(bp) ;    /* drop packet with bad checksum */
  164.                 sp->errors++ ;    /* increment error count */
  165.                 return NULLBUF ;
  166.             }
  167.             break ;
  168.         case NRS_ESCAPE:
  169.             sp->state = NRS_INPACK ;    /* end of escape */
  170.             break ;            /* this will drop through to char processing */
  171.         case NRS_INPACK:
  172.             switch ((c & 0xff)) {    /* DG2KK: was: uchar(c) */
  173.                 /* If we see an STX in a packet, assume that previous */
  174.                 /* packet was trashed, and start a new packet */
  175.                 case STX:
  176.                     free_p(sp->rbp) ;
  177.                     sp->rbp = NULLBUF ;
  178.                     sp->rcnt = 0 ;
  179.                     sp->csum = 0 ;
  180.                     sp->errors++ ;
  181.                     return NULLBUF ;
  182.                     break ;
  183.                 case ETX:
  184.                     sp->state = NRS_CSUM ;    /* look for checksum */
  185.                     return NULLBUF ;
  186.                     break ;
  187.                 case DLE:
  188.                     sp->state = NRS_ESCAPE ;
  189.                     return NULLBUF ;
  190.                     break ;
  191.             }
  192.     }
  193.     /* If we get to here, it's with a character that's part of the packet.
  194.      * Make sure there's space for it.
  195.      */
  196.     if(sp->rbp == NULLBUF){
  197.         /* Allocate first mbuf for new packet */
  198.         if((sp->rbp1 = sp->rbp = alloc_mbuf(NRS_ALLOC)) == NULLBUF) {
  199.             sp->state = NRS_INTER ;
  200.             return NULLBUF; /* No memory, drop */
  201.         }
  202.         sp->rcp = sp->rbp->data;
  203.     } else if(sp->rbp1->cnt == NRS_ALLOC){
  204.         /* Current mbuf is full; link in another */
  205.         if((sp->rbp1->next = alloc_mbuf(NRS_ALLOC)) == NULLBUF){
  206.             /* No memory, drop whole thing */
  207.             free_p(sp->rbp);
  208.             sp->rbp = NULLBUF;
  209.             sp->rcnt = 0;
  210.             sp->state = NRS_INTER ;
  211.             return NULLBUF;
  212.         }
  213.         sp->rbp1 = sp->rbp1->next;
  214.         sp->rcp = sp->rbp1->data;
  215.     }
  216.     /* Store the character, increment fragment and total
  217.      * byte counts
  218.      */
  219.     *sp->rcp++ = c;
  220.     sp->rbp1->cnt++;
  221.     sp->rcnt++;
  222.     sp->csum += (c & 0xff);        /* DG2KK: uchar(c) */ /* add to checksum */
  223.     return NULLBUF;
  224. }
  225.  
  226. /* Process net/rom serial line I/O */
  227. int
  228. nrs_recv(interface)
  229. struct interface *interface;
  230. {
  231.     char c;
  232.     struct mbuf *bp;
  233.     int16 dev;
  234.     int16 asy_recv();
  235.     int ax_recv() ;
  236.  
  237.     dev = interface->dev;
  238.     /* Process any pending input */
  239.     while(asy_recv(dev,&c,1) != 0)
  240.         if((bp = nrs_decode(dev,c)) != NULLBUF) {
  241.             dump(interface,IF_TRACE_IN,TRACE_AX25,bp) ;
  242.             ax_recv(interface,bp);
  243.         }
  244.  
  245.     /* Kick the transmitter if it's idle */
  246.     if(stxrdy(dev))
  247.         nrasy_start(dev);
  248. }
  249.  
  250. /* donrstat:  display status of active net/rom serial interfaces */
  251. donrstat(argc,argv)
  252. int argc ;
  253. char *argv[] ;
  254. {
  255.     register struct nrs *np ;
  256.     register int i ;
  257.  
  258.     printf("Interface  SndQ  RcvB  NumReceived  CSumErrors\n") ;
  259.  
  260.     for (i = 0, np = nrs ; i < ASY_MAX ; i++, np++)
  261.         if (np->iface != NULLIF)
  262.             printf(" %8s   %3d  %4d   %10lu  %10lu\n",
  263.                     np->iface->name, np->sndcnt, np->rcnt,
  264.                     np->packets, np->errors) ;
  265.  
  266.     return 0 ;
  267. }
  268.